package com.zenithmind.library.controller;

import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.library.pojo.dto.BorrowBookDTO;
import com.zenithmind.library.pojo.dto.RenewBookDTO;
import com.zenithmind.library.pojo.dto.ReturnBookDTO;
import com.zenithmind.library.pojo.query.BorrowRecordQuery;
import com.zenithmind.library.pojo.vo.BorrowRecordVO;
import com.zenithmind.library.pojo.vo.BorrowStatisticsVO;
import com.zenithmind.library.service.BorrowService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.List;

/**
 * 借阅管理控制器
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@RestController
@RequestMapping("/api/zenithMind/v1/borrows")
@RequiredArgsConstructor
@Tag(name = "借阅管理", description = "图书借阅、归还、续借等操作")
public class BorrowController {

    private final BorrowService borrowService;

    @PostMapping("/borrow")
    @Operation(summary = "借阅图书", description = "用户借阅图书")
    @PreAuthorize("hasAuthority('library:borrow:create')")
    public Result<BorrowRecordVO> borrowBook(@Valid @RequestBody BorrowBookDTO borrowDTO) {
        log.info("借阅图书，数据：{}", borrowDTO);
        return borrowService.borrowBook(borrowDTO);
    }

    @PostMapping("/return")
    @Operation(summary = "归还图书", description = "用户归还图书")
    @PreAuthorize("hasAuthority('library:borrow:update')")
    public Result<BorrowRecordVO> returnBook(@Valid @RequestBody ReturnBookDTO returnDTO) {
        log.info("归还图书，数据：{}", returnDTO);
        return borrowService.returnBook(returnDTO);
    }

    @PostMapping("/renew")
    @Operation(summary = "续借图书", description = "用户续借图书")
    @PreAuthorize("hasAuthority('library:borrow:update')")
    public Result<BorrowRecordVO> renewBook(@Valid @RequestBody RenewBookDTO renewDTO) {
        log.info("续借图书，数据：{}", renewDTO);
        return borrowService.renewBook(renewDTO);
    }

    @GetMapping
    @Operation(summary = "分页查询借阅记录", description = "根据条件分页查询借阅记录")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<PageResult<BorrowRecordVO>> getBorrowRecordPage(@Valid BorrowRecordQuery query) {
        log.info("分页查询借阅记录，查询条件：{}", query);
        PageResult<BorrowRecordVO> result = borrowService.getBorrowRecordPage(query);
        return Result.success(result);
    }

    @GetMapping("/user/{userId}")
    @Operation(summary = "查询用户借阅记录", description = "根据用户ID查询借阅记录")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<PageResult<BorrowRecordVO>> getBorrowRecordsByUser(
            @Parameter(description = "用户ID", required = true) @PathVariable String userId,
            @Valid BorrowRecordQuery query) {
        log.info("查询用户借阅记录，用户ID：{}，查询条件：{}", userId, query);
        PageResult<BorrowRecordVO> result = borrowService.getBorrowRecordsByUser(userId, query);
        return Result.success(result);
    }

    @GetMapping("/book/{bookId}")
    @Operation(summary = "查询图书借阅记录", description = "根据图书ID查询借阅记录")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<PageResult<BorrowRecordVO>> getBorrowRecordsByBook(
            @Parameter(description = "图书ID", required = true) @PathVariable String bookId,
            @Valid BorrowRecordQuery query) {
        log.info("查询图书借阅记录，图书ID：{}，查询条件：{}", bookId, query);
        PageResult<BorrowRecordVO> result = borrowService.getBorrowRecordsByBook(bookId, query);
        return Result.success(result);
    }

    @GetMapping("/user/{userId}/current")
    @Operation(summary = "查询用户当前借阅", description = "查询用户当前借阅的图书")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<List<BorrowRecordVO>> getCurrentBorrowsByUser(
            @Parameter(description = "用户ID", required = true) @PathVariable String userId) {
        log.info("查询用户当前借阅，用户ID：{}", userId);
        List<BorrowRecordVO> result = borrowService.getCurrentBorrowsByUser(userId);
        return Result.success(result);
    }

    @GetMapping("/overdue")
    @Operation(summary = "查询逾期借阅记录", description = "查询逾期的借阅记录")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<PageResult<BorrowRecordVO>> getOverdueBorrows(@Valid BorrowRecordQuery query) {
        log.info("查询逾期借阅记录，查询条件：{}", query);
        PageResult<BorrowRecordVO> result = borrowService.getOverdueBorrows(query);
        return Result.success(result);
    }

    @GetMapping("/due-soon")
    @Operation(summary = "查询即将到期借阅记录", description = "查询即将到期的借阅记录")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<PageResult<BorrowRecordVO>> getDueSoonBorrows(
            @Parameter(description = "提前天数", required = true) @RequestParam Integer days,
            @Valid BorrowRecordQuery query) {
        log.info("查询即将到期借阅记录，天数：{}，查询条件：{}", days, query);
        PageResult<BorrowRecordVO> result = borrowService.getDueSoonBorrows(days, query);
        return Result.success(result);
    }

    @GetMapping("/check/user/{userId}/book/{bookId}")
    @Operation(summary = "检查用户是否可以借阅", description = "检查用户是否可以借阅指定图书")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<Boolean> canUserBorrow(
            @Parameter(description = "用户ID", required = true) @PathVariable String userId,
            @Parameter(description = "图书ID", required = true) @PathVariable String bookId) {
        log.info("检查用户是否可以借阅，用户ID：{}，图书ID：{}", userId, bookId);
        return borrowService.canUserBorrow(userId, bookId);
    }

    @GetMapping("/check/book/{bookId}")
    @Operation(summary = "检查图书是否可以借阅", description = "检查图书是否可以被借阅")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<Boolean> canBookBeBorrowed(
            @Parameter(description = "图书ID", required = true) @PathVariable String bookId) {
        log.info("检查图书是否可以借阅，图书ID：{}", bookId);
        return borrowService.canBookBeBorrowed(bookId);
    }

    @GetMapping("/{id}/fine")
    @Operation(summary = "计算罚金", description = "计算借阅记录的罚金金额")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<Double> calculateFine(
            @Parameter(description = "借阅记录ID", required = true) @PathVariable String id) {
        log.info("计算罚金，借阅记录ID：{}", id);
        return borrowService.calculateFine(id);
    }

    @PostMapping("/{id}/pay-fine")
    @Operation(summary = "支付罚金", description = "支付借阅记录的罚金")
    @PreAuthorize("hasAuthority('library:borrow:update')")
    public Result<Void> payFine(
            @Parameter(description = "借阅记录ID", required = true) @PathVariable String id,
            @Parameter(description = "支付金额", required = true) @RequestParam Double amount) {
        log.info("支付罚金，借阅记录ID：{}，金额：{}", id, amount);
        return borrowService.payFine(id, amount);
    }

    @PostMapping("/{id}/reminder")
    @Operation(summary = "发送到期提醒", description = "发送图书到期提醒")
    @PreAuthorize("hasAuthority('library:borrow:update')")
    public Result<Void> sendDueReminder(
            @Parameter(description = "借阅记录ID", required = true) @PathVariable String id) {
        log.info("发送到期提醒，借阅记录ID：{}", id);
        return borrowService.sendDueReminder(id);
    }

    @PostMapping("/batch-reminder")
    @Operation(summary = "批量发送到期提醒", description = "批量发送图书到期提醒")
    @PreAuthorize("hasAuthority('library:borrow:update')")
    public Result<Integer> batchSendDueReminders(
            @Parameter(description = "提前天数", required = true) @RequestParam Integer days) {
        log.info("批量发送到期提醒，天数：{}", days);
        return borrowService.batchSendDueReminders(days);
    }

    @GetMapping("/statistics")
    @Operation(summary = "获取借阅统计", description = "获取借阅统计信息")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<BorrowStatisticsVO> getBorrowStatistics(
            @Parameter(description = "开始日期") @RequestParam(required = false) 
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) 
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
        log.info("获取借阅统计，开始日期：{}，结束日期：{}", startDate, endDate);
        
        if (startDate == null) {
            startDate = LocalDate.now().minusMonths(1);
        }
        if (endDate == null) {
            endDate = LocalDate.now();
        }
        
        BorrowStatisticsVO result = borrowService.getBorrowStatistics(startDate, endDate);
        return Result.success(result);
    }

    @GetMapping("/statistics/user/{userId}")
    @Operation(summary = "获取用户借阅统计", description = "获取指定用户的借阅统计信息")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<BorrowStatisticsVO> getUserBorrowStatistics(
            @Parameter(description = "用户ID", required = true) @PathVariable String userId,
            @Parameter(description = "开始日期") @RequestParam(required = false) 
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) 
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
        log.info("获取用户借阅统计，用户ID：{}，开始日期：{}，结束日期：{}", userId, startDate, endDate);
        
        if (startDate == null) {
            startDate = LocalDate.now().minusMonths(1);
        }
        if (endDate == null) {
            endDate = LocalDate.now();
        }
        
        BorrowStatisticsVO result = borrowService.getUserBorrowStatistics(userId, startDate, endDate);
        return Result.success(result);
    }

    @GetMapping("/statistics/book/{bookId}")
    @Operation(summary = "获取图书借阅统计", description = "获取指定图书的借阅统计信息")
    @PreAuthorize("hasAuthority('library:borrow:query')")
    public Result<BorrowStatisticsVO> getBookBorrowStatistics(
            @Parameter(description = "图书ID", required = true) @PathVariable String bookId,
            @Parameter(description = "开始日期") @RequestParam(required = false) 
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) 
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
        log.info("获取图书借阅统计，图书ID：{}，开始日期：{}，结束日期：{}", bookId, startDate, endDate);
        
        if (startDate == null) {
            startDate = LocalDate.now().minusMonths(1);
        }
        if (endDate == null) {
            endDate = LocalDate.now();
        }
        
        BorrowStatisticsVO result = borrowService.getBookBorrowStatistics(bookId, startDate, endDate);
        return Result.success(result);
    }

    @GetMapping("/export")
    @Operation(summary = "导出借阅记录", description = "导出借阅记录到Excel文件")
    @PreAuthorize("hasAuthority('library:borrow:export')")
    public Result<String> exportBorrowRecords(@Valid BorrowRecordQuery query) {
        log.info("导出借阅记录，查询条件：{}", query);
        return borrowService.exportBorrowRecords(query);
    }

    @PostMapping("/auto-process-overdue")
    @Operation(summary = "自动处理逾期记录", description = "自动处理逾期的借阅记录")
    @PreAuthorize("hasAuthority('library:borrow:update')")
    public Result<Integer> autoProcessOverdueRecords() {
        log.info("自动处理逾期记录");
        return borrowService.autoProcessOverdueRecords();
    }
}
